package com.mazaiting.demo.controller;

import com.mazaiting.minio.domain.FileInfo;
import com.mazaiting.minio.domain.PolicyInfo;
import com.mazaiting.minio.ex.MinioException;
import com.mazaiting.minio.service.IMinioService;
import io.minio.messages.Bucket;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * minio 控制器
 *
 * @author mazaiting
 * @create_time 2022/10/7 19:14
 */
@Slf4j
@RestController
@RequestMapping("minio")
@RequiredArgsConstructor
public class MinioController {

    private final IMinioService minioService;

    /**
     * 上传一个文件
     *
     * @return 文件路径
     */
    @PostMapping("/uploadFile")
    public Map<String, String> uploadFile(@RequestParam("file") MultipartFile multipartFile, @RequestParam String bucketName,
                                          @RequestParam(required = false) String objectName) throws Exception {
        minioService.createBucket(bucketName);
        String data;
        if (objectName != null) {
            data = minioService.putObject(bucketName, objectName, multipartFile);
        } else {
            data = minioService.putObject(bucketName, multipartFile.getOriginalFilename(), multipartFile);
        }
        return Collections.singletonMap("url", data);
    }

    /**
     * 列出所有的桶
     */
    @GetMapping("listBuckets")
    public List<String> listBuckets() throws Exception {
        return minioService.getAllBuckets().stream().map(Bucket::name).toList();
    }

    /**
     * 递归列出一个桶中的所有文件和目录
     *
     * @return 文件列表
     */
    @GetMapping("/listFiles")
    public List<FileInfo> listFiles(@RequestParam String bucketName) {
        return minioService.listFiles(bucketName);
    }

    /**
     * 下载一个文件
     */
    @GetMapping("/downloadFile")
    public void downloadFile(@RequestParam String bucketName, @RequestParam String objectName,
                             HttpServletResponse response) throws Exception {
        InputStream stream = minioService.getObject(bucketName, objectName);
        ServletOutputStream output = response.getOutputStream();
        // 构建下载类型
        ContentDisposition attachment = ContentDisposition.attachment().filename(URLEncoder.encode(objectName.substring(objectName.lastIndexOf("/") + 1), StandardCharsets.UTF_8)).build();
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, attachment.toString());
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        IOUtils.copy(stream, output);
    }

    /**
     * 删除一个文件
     */
    @DeleteMapping(value = "/deleteFile")
    public void deleteFile(@RequestParam String bucketName, @RequestParam String objectName) throws Exception {
        minioService.removeObject(bucketName, objectName);
    }

    /**
     * 删除一个桶
     */
    @DeleteMapping(value = "/deleteBucket")
    public void deleteBucket(@RequestParam String bucketName) throws MinioException {
        minioService.removeBucket(bucketName);
    }

    /**
     * 获取临时授权-用于上传文件
     * h5 请求参数:
     *  file: <文件>
     *  x-amz-algorithm: "AWS4-HMAC-SHA256"
     *  x-amz-credential: "admin/20221007/us-east-1/s3/aws4_request"
     *  key: "文件名"
     *  x-amz-signature: "836c571bfbcb9df0bce00f0fa14a60aea6f3884c9174f9cbe42fd49d852516ad"
     *  x-amz-date: "20221007T155728Z"
     *  policy: "eyJleHBpcmF0aW9uIjoiMjAyMi0xMC0wN1QxNjowNzoyOC40NjJaIiwiY29uZGl0aW9ucyI6W1siZXEiLCIkYnVja2V0IiwidGVzdCJdLFsiZXEiLCIka2V5IiwiNzEyNjA4NmYzOTY2MjI4ODUyZTY3NjA1ZDcwMjQyNWQuanBlZyJdLFsiZXEiLCIkeC1hbXotYWxnb3JpdGhtIiwiQVdTNC1ITUFDLVNIQTI1NiJdLFsiZXEiLCIkeC1hbXotY3JlZGVudGlhbCIsImFkbWluLzIwMjIxMDA3L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QiXSxbImVxIiwiJHgtYW16LWRhdGUiLCIyMDIyMTAwN1QxNTU3MjhaIl1dfQ=="
     *
     * @param bucketName 存储桶名
     * @param objectName 文件名
     * @return 协议参数
     */
    @GetMapping("policy")
    public PolicyInfo policy(@RequestParam String bucketName, String objectName) throws MinioException {
        return minioService.policy(bucketName, objectName);
    }

}
